/** 
 * The "main" file, the one file to rule them
 * all. 
 * 
 * Comments updated for April 2nd.
 * Most of them should hopefully
 * be self explanatory.
 * 
 * @author Andrew
 * @creator - Andrew 
 *          - David(two player functions)
 *          - Calvin(a few power bar additions)
 * LAST UPDATED - Andrew 2/4/12
 */

/** CONTAINS:
 * 
 * StartUp() runs the OpenGL code for
 * setting up display.
 * 
 * LoadingScreen() is a simple function to
 * draw a screen before loading a large segment.
 * 
 * MainMenu() is the function for the main menu.
 * Returns values that are input into the game to
 * tell it what the user wants.
 * 
 * Start() is the main game function. Takes various
 * arguments, explained in the function
 * 
 * And of course main, which runs these functions.
 * 
 * StartUp -> loadingScreen -> mainMenu -> loadingScreen
 * -> Start().
 */

// Needed imports
// lwjgl is the OpenGL (Open Graphics Library) for java
// This allows keyboard input.
import org.lwjgl.input.Keyboard;
// this is for Display
import org.lwjgl.opengl.Display;
// Setting Display settings like size.
import org.lwjgl.opengl.DisplayMode;
// Exception for screen failing
import org.lwjgl.LWJGLException;
// openAL is Open Audio Library. Allows sound
import org.lwjgl.openal.AL;
// Slick Utilities store for all openAL sounds
import org.newdawn.slick.openal.SoundStore;



public class Game {
	
	public void startUp() {
		try {
			// Create new window with width 900, height 800
			// Game window bottom left at 0,300
			Display.setDisplayMode(new DisplayMode(900, 800));
			Display.create();
		} catch (LWJGLException e) { // If theres an error
			e.printStackTrace(); // print it
			System.exit(0); // and close the window and program
		}

		// Initialize the window
		// This function renders the screen, sets the perception of the screen
		// and allows various other things like transparency
		JGE.initJGE();
	}
	
	// Really simple function for displaying the loading screen
	public void loadingScreen() {
		// Load the loading screen
		SimpleObject bg = new SimpleObject(0,0,"loading.png");
		// Draw it to the screen
		bg.draw(); 
		// Update the display so it can be seen
		Display.update();
	}
	
	// The main menu function, returns GameData, for start() to use later.
	public GameData mainMenu() {
		// Setting up many standard ints and bools here
		boolean mainMenu = true;                                     // Are you on the mainMenu screen?
		boolean credits = false;                                     // Are you on the Credits screen?
		boolean singleplayer = false;                                // Are you on the singleplayer screen?
		boolean multiplayer = false;                                // Are you on the multiplayer screen?
		boolean pmove = false;                                      // Have you moved the pointer recently?
		boolean returned = false;                                   // Have you hit return recently?
		Timer ptimer = new Timer();                                 // Timer to keep track of the pointer movement
		Timer rtimer = new Timer();                                 // Timer to keep track of the return key
		
		/**
		 * The pmove and returned booleans as well as ptimer and rtimer are needed because:
		 * They way lwjgl key commands work is that when you hit the key, it is down for more than one frame
		 * and it will move each frame, which is not what we want.
		 * 
		 * So as soon as the key is pressed pmove or rmove becomes true, and only resets after a certain amount 
		 * of miliseconds. This way you get smooth movement.
		 */
		
		// The Objects for the various screens
		SimpleObject mm = new SimpleObject(0,0,"MM.png");                                    // MainMenu
		SimpleObject cr = new SimpleObject(0,0,"Credits.png");                               // Credits
		SimpleObject sp = new SimpleObject(0,0,"SinglePlayerOptions.png");                   // Single Player
		SimpleObject mp = new SimpleObject(0,0,"MultiplayerOptions.png");                    // Multiplayer
		SimpleObject pointer = new SimpleObject(0,0,"pointer.png");                          // The main Pointer
		SimpleObject mapPointer = new SimpleObject(0,0,"smallPointer.png");                  // Three small pointers for options
		SimpleObject windPointer = new SimpleObject(0,0,"smallPointer.png");
		SimpleObject picPointer = new SimpleObject(0,0,"smallPointer.png");
		int selected = 0;                      // Int to tell me what is selected
		int mapSelect = 0;                     // Int for which map is currently selected
		boolean wind = false;                  // boolean for wind on or off
		int picSelect = 0;                     // Int for picture selection
		
		
		// While the user does not close the screen with the small x (NOT esc key)
		while(!Display.isCloseRequested()) {
			// If you havent pressed an arrow key recently then we dont need to time it.
			if(!pmove) {
				ptimer.reset();
			}
			// Same for return key
			if(!returned) {
				rtimer.reset();
			}
			// WHen your on the mainMenu...
			if(mainMenu) {
				// Draw the main menu screen
				mm.draw();
				// If things are selected, move the pointer accordingly
				if(selected == 0) {
					pointer.setX(280);
					pointer.setY(540);
				}
				else if(selected == 1) {
					pointer.setX(290);
					pointer.setY(385);
				}
				else if(selected == 2) {
					pointer.setX(347);
					pointer.setY(220);
				}
				// If you pressed enter...
				if(Keyboard.isKeyDown(Keyboard.KEY_RETURN)) {
					// And you are allowed to press enter
					if(!returned) {
						// then you are leaving the main menu
						mainMenu = false;
						// And you just hit enter
						returned = true;
						// Depending on what you have selected then change the screen to the correct one
						// Also make selected 0, so that you start at the right side
						if(selected == 0) {
							selected = 0;
							singleplayer = true;
						}
						else if(selected == 1) {
							selected = 0;
							multiplayer = true;
						}
						else if(selected == 2) {
							selected = 0;
							credits = true;
						}
					}
				}
			}
			// If your on the credits screen
			else if(credits) {
				// Draw it
				cr.draw();
				// If you press escape then go back to the main menu
				if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
					credits = false;
					mainMenu = true;
				}
			}
			// If your on the single player screen
			else if(singleplayer) {
				// Draw it
				sp.draw();
				// Move the pointer according to what is selected
				if(selected == 0) {
					pointer.setX(1);
					pointer.setY(505);
				}
				else if(selected == 1) {
					pointer.setX(340);
					pointer.setY(515);
				}
				else if(selected == 2) {
					pointer.setX(660);
					pointer.setY(510);
				}
				// And the mapPointer...
				if(mapSelect == 0) {
					mapPointer.setX(60);
					mapPointer.setY(435);
				}
				else if(mapSelect == 1) {
					mapPointer.setX(60);
					mapPointer.setY(390);
				}
				else if(mapSelect == 2) {
					mapPointer.setX(60);
					mapPointer.setY(340);
				}
				else if(mapSelect == 3) {
					mapPointer.setX(60);
					mapPointer.setY(280);
				}
				else if(mapSelect == 4) {
					mapPointer.setX(60);
					mapPointer.setY(225);
				}
				// And windPointer...
				if(wind) {
					windPointer.setX(405);
					windPointer.setY(445);
				}
				else if(!wind) {
					windPointer.setX(405);
					windPointer.setY(403);
				}
				// ANd picture pointer...
				if(picSelect == 0) {
					picPointer.setX(650);
					picPointer.setY(445);
				}
				else if(picSelect == 1) {
					picPointer.setX(645);
					picPointer.setY(392);
				}
				else if(picSelect == 2) {
					picPointer.setX(635);
					picPointer.setY(337);
				}
				else if(picSelect == 3) {
					picPointer.setX(645);
					picPointer.setY(278);
				}
				else if(picSelect == 4) {
					picPointer.setX(645);
					picPointer.setY(222);
				}
				// Draw all the pointers
				picPointer.draw();
				windPointer.draw();
				mapPointer.draw();
				// If you pressed escape go back to the main menu and reset selected.
				if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
					selected = 0;
					singleplayer = false;
					mainMenu = true;
				}
				// If you hit enter and your allowed, finish the program and return the currently selected values.
				if(Keyboard.isKeyDown(Keyboard.KEY_RETURN)) {
					if(!returned) {
						return(new GameData(mapSelect,wind,picSelect,false));
					}
				}
			}
			// The same as single player only you return true in the GameData creation because you want two player.
			else if(multiplayer) {
				mp.draw();
				if(selected == 0) {
					pointer.setX(1);
					pointer.setY(505);
				}
				else if(selected == 1) {
					pointer.setX(340);
					pointer.setY(515);
				}
				else if(selected == 2) {
					pointer.setX(660);
					pointer.setY(510);
				}
				
				if(mapSelect == 0) {
					mapPointer.setX(60);
					mapPointer.setY(435);
				}
				else if(mapSelect == 1) {
					mapPointer.setX(60);
					mapPointer.setY(390);
				}
				else if(mapSelect == 2) {
					mapPointer.setX(60);
					mapPointer.setY(340);
				}
				else if(mapSelect == 3) {
					mapPointer.setX(60);
					mapPointer.setY(280);
				}
				else if(mapSelect == 4) {
					mapPointer.setX(60);
					mapPointer.setY(225);
				}
				if(wind) {
					windPointer.setX(405);
					windPointer.setY(445);
				}
				else if(!wind) {
					windPointer.setX(405);
					windPointer.setY(403);
				}
				if(picSelect == 0) {
					picPointer.setX(650);
					picPointer.setY(445);
				}
				else if(picSelect == 1) {
					picPointer.setX(645);
					picPointer.setY(392);
				}
				else if(picSelect == 2) {
					picPointer.setX(635);
					picPointer.setY(337);
				}
				else if(picSelect == 3) {
					picPointer.setX(645);
					picPointer.setY(278);
				}
				else if(picSelect == 4) {
					picPointer.setX(645);
					picPointer.setY(222);
				}
				picPointer.draw();
				windPointer.draw();
				mapPointer.draw();
				if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
					selected = 0;
					multiplayer = false;
					mainMenu = true;
				}
				if(Keyboard.isKeyDown(Keyboard.KEY_RETURN)) {
					if(!returned) {
						return(new GameData(mapSelect,wind,picSelect,true));
					}
				}
			}
			// If your not on the credits page, draw the pointer (the credits page doesnt have anything to select)
			if (!credits) pointer.draw();
			// If you press up, and your allowed
			if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
				if(!pmove) {
					// If your on Single or multiplayer
					if(!mainMenu && !credits) {
						// Depending on what you have selected you must move the Secondary pointer
						if(selected == 0) {
							mapSelect -= 1;
							// But if it gets too low or high, then change it back to the highest or lowest value, respectively
							if(mapSelect < 0) {      
								mapSelect = 4;
							}
							// but either way you moved a pointer
							pmove = true;
						}
						else if(selected == 1) {
							wind = !wind;
							pmove = true;
						}
						else if(selected == 2) {
							picSelect -= 1;
							if(picSelect < 0) {
								picSelect = 4;
							}
							pmove = true;
						}
					}
					// If your on the main menu move the pointer as before
					if(mainMenu) {
						selected -= 1;
						if(selected < 0) {
							selected = 2;
						}
						pmove = true;
					}
				}
			}
			// The same as up arrow but all minus' become additions
			if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
				if(!pmove) {
					if(!mainMenu && !credits) {
						if(selected == 0) {
							mapSelect += 1;
							if(mapSelect > 4) {
								mapSelect = 0;
							}
						}
						else if(selected == 1) {
							wind = !wind;
							pmove = true;
						}
						else if(selected == 2) {
							picSelect += 1;
							if(picSelect > 4) {
								picSelect = 0;
							}
							pmove = true;
						}
					}
					if(mainMenu) {
					selected += 1;
						if(selected > 2) {
							selected = 0;
						}
					}
					pmove = true;
				}
			}
			// same as all the stuff before but only on single and multiplayer pages
			if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
				if(!pmove) {
					if(!credits && !mainMenu) {
					selected += 1;
						if(selected > 2) {
							selected = 0;
						}
					}
					pmove = true;
				}
			}
			// as with right key
			if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
				if(!pmove) {
					if(!credits && !mainMenu) {
						selected -= 1;
						if(selected < 0) {
							selected = 2;
						}
						pmove = true;
					}
					}
			}
			// update the display so we can see all the changes
			Display.update();
			// if the timer has got to 150 miliseconds, allow us to use the pointer keys again
			if(ptimer.getDeltaTime() > 150) {
				pmove = false;
			}
			// and the same with return, but a bit longer, we dont want to accidently start a game
			if(rtimer.getDeltaTime() > 400) {
				returned = false;
			}
			
		}
		// if close is requested before you start a game, destroy the display, exit program
		Display.destroy();
		System.exit(0);
		// return some rubish because eclipse complains if you dont, goddamn you eclipse!
		return(new GameData(0,false,0,false));
	}

	// The main function. This is called once and runs until the end.
	// Throws an exception thanks to the music, if it ever gets interupted by something. It never does but hey if it did, we have it covered!
	
	/**
	 * 
	 * @param mapp   - an int, tells us what map the player wants
	 * @param windp  - a boolean, tells us if the wind is on or not
	 * @param picp   - an int, tells us what picture the player wants
	 * @param twoplayerp - a boolean is it two player?
	 * @throws InterruptedException 
	 */
	public void start(int mapp,boolean windp,int picp,boolean twoplayerp) throws InterruptedException {

		// set some values so I can change them (I think - but not sure that the values given are static and I cant change them)
		// not sure about that, but better be safe.
		int mapi = mapp;
		boolean windi = windp;
		int pic = picp;
		boolean twoplayer = twoplayerp;
		
		// This massive section (Before the while loop) defines the starting conditions.
		
		
		// a random number which is either 1 or -1.
		int nii;
		if(Math.random() >= 0.5) nii = 1;
		else nii = -1;
		// Use this random number so that the angles you start at are 0 +- 30 degrees.
		// The player is refered to as you. The enemy (or other player now) is target. hence angleyou and angletar
		double angleyou = ((Math.random() * 30) * nii);
		double angletar = ((Math.random() * 30) * nii);
		// Starting velocity is 7, but this is no longer needed. Its just here to keep some functions happy.
		double vel = 7.0;

		
		double wind;
		// The Wind is a random value between 0 and 10
		// If the wind is allowed then its a random number in a random direction (but either left or right, not up or down or whathave you)
		if(windi) {
			wind = Math.random() * 10 * nii;
			System.out.println("The wind today is: " + wind);
		}
		// Else its 0, but either way print what it is.
		else {
			wind = 0;
			System.out.println("The wind today is: " + wind);
		}
		

		// No ball is being fired at the start
		// Tells us if a ball is being fired
		boolean ballfire = false;

		// No fire animation at the start
		// Tells us whether there is a firing animation going on
		boolean firing = false;

		// space bar down?
		// pretty redundant looking at it now, but im sure it served a purpose once upon a time.
		boolean space = false;
		
		// IS THE AI ON?!!! - if its two player then obviously not, it it isnt then AI is on.
		boolean AI = !twoplayer;
		

		// create a simple box, which is our background, at 0,0
		// if the choice is 4 which is random then generate a random choice
		if(pic == 4) {
			double selector = Math.random() * 4;
			if(selector > 3) {
				pic = 3;
			}
			else if(selector > 2) {
				pic = 2;
			}
			else if(selector > 1) {
				pic = 1;
			}
			else if(selector >= 0) {
				pic = 0;
			}
		}
		// standard initialization
		SimpleObject bg = JGE.newObject(0, 200, "testbg.png");
		// Change it to the right one, according to the choice
		if(pic == 0) {
			bg = JGE.newObject(0, 200, "Castle.png");
		}
		else if(pic == 1) {
			bg = JGE.newObject(0, 200, "Volc.png");
		}
		else if(pic == 2) {
			bg = JGE.newObject(0, 200, "DBS.png");
		}
		else if(pic == 3) {
			bg = JGE.newObject(0, 200, "testbg.png");
		}
		

		// create the border and frame it.
		SimpleObject border = JGE.newObject(0, 0, "blueborder.png");

		// create the powerbar
		PowerBar pb = new PowerBar(350, 40);

		// Create a tank to be the player at 0,0 - Yes we call them tanks even though they are catapults, get over it
		TankObject you = JGE.newTank(0, 248);
		// adjust the health bar of You so that it
		// Looks about right.
		you.adjustHealthBar(130, 75);

		// Create a tank to be the target some distance away from the player.
		TankObject target = JGE.newTank(900 - you.getWidth(), 248);
		// Reverse it so it looks at the player
		target.reverse();

		// Ajust its health and ammobars to be in correct position
		target.adjustHealthBar(785, 75);
		target.adjustAmmoBar(725, 50);

		// BackGround Music
		// Again standard random generation
		double musicrandom = Math.random() * 10;
		int p = 0;
		if (musicrandom >= 6.66)
			p = 1;
		else if (musicrandom >= 3.33)
			p = 2;
		else if (musicrandom >= 0)
			p = 3;
		// Sound files are bg + a number and are in .ogg format for ease of use. 
		Sound music = new Sound("bg" + p + ".ogg");
		// play the music - as music, Not a sound effect - this loops the music
		music.playMusic();
		
		// the main ball, create it at the players tank, around where the ball is realeased from. it also needs to know your angle and the wind
		ProjectileObject ball = JGE.newMissile(target.getWidth() - 31,
				target.getHeight() + 5 + 248, vel, angleyou, wind);
		
		// Create the AI! A starting angle,power, the wind value, the projectile to fire and which side its on (right is false, left is true)
		AI2 ai = new AI2(45.0,8.6,wind,ball,false);
		

		// Secondary balls - for the 5th ammo when you have 3 balls
		ProjectileObject sball1 = JGE.newMissile(target.getWidth() - 31,
				target.getHeight() + 5 + 248, vel, angleyou, wind);
		ProjectileObject sball2 = JGE.newMissile(target.getWidth() - 31,
				target.getHeight() + 5 + 248, vel, angleyou, wind);

		
		// Map generation - create an instance of the class DefaultMap
		DefaultMap n = new DefaultMap();
		// pick the default map for now
		Map tileList = n.defaultMap;
		
		// if choice is random, pick randomly
		if(mapi == 3) {
			double selector2 = Math.random() * 3;
			if(selector2 > 2) {
				mapi = 2;
			}
			else if(selector2 > 1) {
				mapi = 1;
			}
			else if(selector2 >= 0) {
				mapi = 0;
			}
		}
		// According to choice pick the map
		if(mapi == 0) {
			tileList = n.defaultMap;
		}
		else if(mapi == 1) {
			DefaultMap2 newmap = new DefaultMap2();
			tileList = newmap.mounded;
		}
		else if(mapi == 2) {
			tileList = n.hardMap;
		}
		else if(mapi == 4) {
			tileList = n.random;
		}
		// Make sure all the tiles Neighbours are null before setting them
		tileList.resetAll();
		// Tell the tiles what their neighbours are, based on the screen size
		tileList.setNeighbours(900, 800);
		// And the make sure all the tiles look like they are supposed to.
		tileList.update();

		// Create timer which counts how long a frame is
		Timer frameTimer = new Timer();

		// Create the PowerBar Timer - for counting how long you hold it down
		Timer powerTimer = new Timer();

		// Is the player on his last ammo?
		boolean lastAmmo = false;
		
		// A boolean to make switching sides possible
		boolean switched = false;
		
		
		// Frame rate counter
		// the count of frames so far
		int ncount = 0;
		
		// the count of total time so far
		int total = 0;
		
		// change the angles of the target and you's laser sights, to what their angles are
		// THey are different because one is pointing left and one right. Reverse doesnt work because your not
		// reversing the texture, but the position
		target.ls.changeAngle(180+angletar);
		you.ls.changeAngle(-angleyou);
		
		
		// And now for the actual game!
		// While you havent closed the screen
		while (!Display.isCloseRequested()) {
			// If the space bar was for some reason held for less than 0.3secs
			// reset the power bar and the space bar is not held down
			if (space == false && powerTimer.getDeltaTime() <= 300) {
				powerTimer.reset();
				space = false;
			} 

			// Reset the Timer and start counting from now
			frameTimer.reset();

			// Reset the screen
			// makes sure that all colour is wiped off so we can start anew.
			JGE.glBufferReset();

			// If the up arrow is pressed increase the angle, unless it is
			// greater
			// than 90, in which case keep it as 90.
			if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
				// ball.getWho() decides whos turn it is, -1 is player, 1 is enemy
				// according to who it is, change their angle and laser sight
				if(ball.getWho() == -1) {
					if (angleyou >= 90) {
						angleyou = 90;
					} 
					else angleyou += 0.5;
				}
				if(ball.getWho() == 1) {
					if (angletar >= 90) {
						angletar = 90;
					} 
					else angletar += 0.5;
				}
				if(ball.getWho() == -1) you.ls.changeAngle(-angleyou);
				else target.ls.changeAngle(180 +angletar);
			}
			// If down arrow is pressed decrease the angle.
			// as before but decreasing angle - minimum is -90
			if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
				if(ball.getWho() == -1) {
					if (angleyou <= -90) {
						angleyou = -90;
					} 
					else angleyou -= 0.5;
				}
				if(ball.getWho() == 1) {
					if (angletar <= -90) {
						angletar = -90;
					} 
					else angletar -= 0.5;
				}
				if(ball.getWho() == -1) you.ls.changeAngle(-angleyou);
				else target.ls.changeAngle(180+angletar);
			}

			// if the user is on his last ammo change it so he is on his standard ammo
			if (lastAmmo) {
				if(ball.getWho() == -1) you.setAmmo(0);
				if(ball.getWho() == 1) target.setAmmo(0);
				lastAmmo = false;
			}
			

			// if a ball is not currently being fired, and both tanks are alive
			
			if (ballfire == false && target.isAlive() == true && you.isAlive()) {
				// you can change your ammo, but only if you have more than 0 left, otherwise do nothing
				if (Keyboard.isKeyDown(Keyboard.KEY_1)) {
					// and also depending on whos turn it is.
					if(ball.getWho() == -1) {
						if (you.getAmmunition(0) > 0)
							you.setAmmo(0);
					}
					else if(ball.getWho() == 1) {
						if(target.getAmmunition(0) > 0) target.setAmmo(0);
					}
				}
				if (Keyboard.isKeyDown(Keyboard.KEY_2)) {
					if(ball.getWho() == -1) {
						if (you.getAmmunition(1) > 0)
							you.setAmmo(1);
					}
					else if(ball.getWho() == 1) {
						if(target.getAmmunition(1) > 0) target.setAmmo(1);
					}
				}
				if (Keyboard.isKeyDown(Keyboard.KEY_3)) {
					if(ball.getWho() == -1) {
						if (you.getAmmunition(2) > 0)
							you.setAmmo(2);
					}
					else if(ball.getWho() == 1) {
						if(target.getAmmunition(2) > 0) target.setAmmo(2);
					}
				}
				if (Keyboard.isKeyDown(Keyboard.KEY_4)) {
					if(ball.getWho() == -1) {
						if (you.getAmmunition(3) > 0)
							you.setAmmo(3);
					}
					else if(ball.getWho() == 1) {
						if(target.getAmmunition(3) > 0) target.setAmmo(3);
					}
				}
				if (Keyboard.isKeyDown(Keyboard.KEY_5)) {
					if(ball.getWho() == -1) {
						if (you.getAmmunition(4) > 0)
							you.setAmmo(4);
					}
					else if(ball.getWho() == 1) {
						if(target.getAmmunition(4) > 0) target.setAmmo(4);
					}
				}

				// make sure that the powerTimer isnt running for no reason
				if (space == false && powerTimer.getDeltaTime() <= 300) {
					powerTimer.reset();
					space = false;
				} 
				// If space is pressed, fire a ball at the current angle
				// and tell the program you are firing a ball
				if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
					if(ball.getWho() == -1) {
						ball.setAngle(angleyou);
					if (you.getAmmo() == 4) {
						// If your ammo is the fith one (n-1 for ammo) then set the angles of the secondary balls.
						sball1.setAngle(angleyou - 5);
						sball2.setAngle(angleyou + 5);
					}
					}
					// same for other player if its their turn
					if(ball.getWho() == 1) {
						ball.setAngle(angletar);
						if (target.getAmmo() == 4) {
							sball1.setAngle(angletar - 5);
							sball2.setAngle(angletar + 5);
						}
					}
					// space bar is down
					space = true;

				}

				// If the Space key is up, then space bar is not down - crafty logic
				if (Keyboard.isKeyDown(Keyboard.KEY_SPACE) == false) {
					space = false;

				}

				// If the space bar is held down, get velocity
				if (space == true) {
					PowerBar.velocity(powerTimer, space);
				}
				
				// make sure it aint running amok again - it does it alot
				if (space == false && powerTimer.getDeltaTime() <= 300) {
					powerTimer.reset();
					space = false;
				} 
				// and it also does it if your frame rate is low, so if it is less than 14fps than reset it aswell
				if (total > 1000 && ncount < 14) {
					powerTimer.reset();
				}
				// But after all that - if you did manage to hold it down for longer than 0.3s and then release it
				if (space == false && powerTimer.getDeltaTime() > 300) {
					// set the velocity
					PowerBar.getvel(ball);
					// and depending on the player
					if(ball.getWho() == -1) {
						// and if their ammo is the 3 ball one
						if (you.getAmmo() == 4) {
							// set secondary balls
							PowerBar.getvel(sball1);
							PowerBar.getvel(sball2);
						}
						// and also  your ammo decreases by 1. If it isnt the standard ball - you have as many as you want
						if(you.getAmmo() != 0) you.setAmmo(you.getAmmo(),
								you.getAmmunition(you.getAmmo()) - 1);
					}
					if(ball.getWho() == 1) {
						if (target.getAmmo() == 4) {
							PowerBar.getvel(sball1);
							PowerBar.getvel(sball2);
						}
						if(target.getAmmo() != 0) target.setAmmo(target.getAmmo(),
								target.getAmmunition(target.getAmmo()) - 1);
					}
			
					// but either way you are now firing a ball
					firing = true;
					// space bar is released
					space = false;
					// and reset the timer
					powerTimer.reset();

				}
				// draw the background first
				bg.draw();
				// then border
				border.draw();
				// then tiles
				for (int i = 0; i < tileList.existingTiles.length; i++) {
					tileList.existingTiles[i].draw();
				}
				
				// For the AI
				if(ball.getWho() == 1 && AI) {
					// get the velocity and angle it wants me to use
					ball.setVelocity(ai.getPower());
					ball.setAngle(ai.getAngle());
					// and tell the world your firing
					firing = true;
					ballfire = false;
				}
				
				// Now to fire the balls
				if (firing && ballfire == false) {
					// reset the ball's position before its fired
					ball.reset();
					// for player 1...
					if(ball.getWho() == -1){
						// you.fire() returns a boolean which tells it if its at the right frame to fire.
						// because the catapult winds up before it fires.
						// you.fire() also runs the animation and sound for us. God bless functions...
						ballfire = you.fire();
						// If the ball needs to change its picture, do so now.
						ball.changeAmmo(you.getAmmo());
						// if your on 3 ball ammo, make sure they are all alive before you fire
						if (you.getAmmo() == 4) {
							ball.setAlive(true);
							sball1.setAlive(true);
							sball2.setAlive(true);
						}
						// if not then just make sure the ball is alive
						else ball.setAlive(true);
					}
					// and again for player 2
					if(ball.getWho() == 1){
						ballfire = target.fire();
						ball.changeAmmo(target.getAmmo());
						if (target.getAmmo() == 4) {
							ball.setAlive(true);
							sball1.setAlive(true);
							sball2.setAlive(true);
						}
						else ball.setAlive(true);
					}
				}
				// Draw the powerbar depending on the time of powerTimer
				pb.draw(powerTimer);
				// then the player
				you.draw();
				// the target
				target.draw();

				// and update the screen so it can be seen
				Display.update();

				// count the frame count, and the total frame time length
				long time = (long) frameTimer.getDeltaTime();
				ncount++;
				total += time;
				
				// Print out the frame rate every second
				if(total > 1000) {
					System.out.println("Frame Rate: " + ncount);
					ncount = 0;
					total = 0;
				}
				
				// If the time to draw the scene was less then 1/60th of a
				// second than wait until 1/60th of a second is over
				// *** Basically limit the game ALWAYS to 60fps.
				if (time < (1000 / 60)) {
					Thread.sleep((long) ((1000 / 60) - time));
				}

				// Note: do not draw the ball as it hasnt been fired!
			}

			// if someone is dead then print out you win. But who?! well you can work it out yourselves
			else if (target.isAlive() == false || you.isAlive() == false) {
				System.out.println("You WIN!!!!!!!!!! HAPPY DAYS");
				// destroy the screen and end program
				Display.destroy();
				return;
			}

			// If a ball IS being fired
			else {
				// draw the Background and border
				bg.draw();
				border.draw();
				// power bar
				pb.draw(powerTimer);
				// and tiles
				for (int i = 0; i < tileList.existingTiles.length; i++) {
					tileList.existingTiles[i].draw();
				}
				// Whos turn is it? and make them continue the fire animation
				if(ball.getWho() == -1) {
					you.fire();
				}
				if(ball.getWho() == 1) {
					target.fire();
				}
				// and draw both players
				you.draw();
				target.draw();
				
				// this makes sure the balls are on the screen, if they arnt then kill them
				// if they are then move them in a parabola
				if(ball.getWho() == -1) {
					if (you.getAmmo() == 4) {
						if(sball1.inBounds(900,800) == false) {
							sball1.setAlive(false);
						}
						else if (sball1.getAlive()) {
							sball1.update();
						}
						if(sball2.inBounds(900,800)==false) {
							sball2.setAlive(false);
						}
						else if (sball2.getAlive()) {
							sball2.update();
						}
					}
				}
				if(ball.getWho() == 1) {
					if (target.getAmmo() == 4) {
						if(sball1.inBounds(900,800) == false) {
							sball1.setAlive(false);
						}
						else if (sball1.getAlive()) {
							sball1.update();
						}
						if(sball2.inBounds(900,800)==false) {
							sball2.setAlive(false);
						}
						else if (sball2.getAlive()) {
							sball2.update();
						}
					}
				}
				// and again for the main ball
				if(ball.inBounds(900,800) == false) {
			        ball.setAlive(false);
				}
				if(ball.getAlive()) {
					ball.update();
				}
				
				// check collisions
				if(ball.getWho() == -1) {
					ball.checkColl(you, target, tileList);
				}
				// and again but if the players turn is reveresed so is the target and player in the function
				if(ball.getWho() == 1) {
					ball.checkColl(target,you, tileList);
				}
				// and if the ammo is the 3 ball check collisions on them too
				if(ball.getWho() == -1) {
					if(you.getAmmo() == 4) {
						sball1.checkColl(you,target,tileList);
						sball2.checkColl(you,target,tileList);
					}
				}
				if(ball.getWho() == 1) {
					if(target.getAmmo() == 4) {
						sball1.checkColl(target,you,tileList);
						sball2.checkColl(target,you,tileList);
					}
				}
		
				// Make sure you havent switched turns already
				if(ball.getWho() == -1 && switched == false) {
					// if its a normal ball
					if (you.getAmmo() != 4) {
						// and its dead
						if (ball.getAlive() == false) {
							// you arnt firing any balls any more
							ballfire = false;
							firing = false;
							// reset the firer to normal frame
							you.reset();
							// change the side and turn of all balls
							ball.changeSide();
							sball1.changeSide();
							sball2.changeSide();
							ball.switchTurn();
							sball1.switchTurn();
							sball2.switchTurn();
							// you just switched turn 
							switched = true;
							// reset the balls position
							ball.reset();
						}
					}
					// if its a 3 ball ammo
					else {
						// and All balls are dead, do the same
						if (ball.getAlive() == false && sball1.getAlive() == false
								&& sball2.getAlive() == false) {
							ball.reset();
							sball1.reset();
							sball2.reset();
							ballfire = false;
							firing = false;
							you.reset();
							ball.changeSide();
							sball1.changeSide();
							sball2.changeSide();
							ball.switchTurn();
							sball1.switchTurn();
							sball2.switchTurn();
							switched = true;
							
						}

					}
				}
				// and again for player one if you havent switched (without switch it changes turn, then changes turn again... not helpful lol)
				if(ball.getWho() == 1 && switched == false) {
					if (target.getAmmo() != 4) {
						if (ball.getAlive() == false) {
							ballfire = false;
							firing = false;
							target.reset();
							ball.changeSide();
							sball1.changeSide();
							sball2.changeSide();
							ball.switchTurn();
							sball1.switchTurn();
							sball2.switchTurn();
							ball.reset();
							switched = true;
							// Oh yeah and here you want to run the AI so that it knows how well it did.
							ai.adjust();
						}
					}
					else{
						if (ball.getAlive() == false && sball1.getAlive() == false
								&& sball2.getAlive() == false) {
							ball.reset();
							sball1.reset();
							sball2.reset();
							ballfire = false;
							firing = false;
							target.reset();
							ball.changeSide();
							sball1.changeSide();
							sball2.changeSide();
							ball.switchTurn();
							sball1.switchTurn();
							sball2.switchTurn();
							switched = true;
							ai.adjust();
							
						}

					}
				}
				// if its ammo is now depleted that was its last ammo.
				if (you.getAmmunition(you.getAmmo()) == 0)
					lastAmmo = true;
				if (target.getAmmunition(target.getAmmo()) == 0)
					lastAmmo = true;

				// But either way update the display
				Display.update();
				// make sure the sound doesnt have a fit.
				SoundStore.get().poll(0);
				// and you now dont need to switch
				switched = false;
				

				// And frame rate/ frame limiting
				long time = (long) frameTimer.getDeltaTime();
				
				ncount++;
				total += time;
				
				if(total > 1000) {
					System.out.println("Frame Rate: " + ncount);
					ncount = 0;
					total = 0;
				}
				
				if (time < (1000 / 60)) {
					Thread.sleep((long) ((1000 / 60) - time));
				}

			}
		}
		// END OF THE WHILE LOOP HERE --------------------------------------------------------------------------------------------------------------
		
		// Once close is requested, destroy the screen
		Display.destroy();
		// And all music samples
		AL.destroy();
	}

	// On program run, make the game and start it.
	public static void main(String[] argv) {
		
		// Make the gameclass
		Game app = new Game();
		// Stupid exception catching...
		try {
			// build screen
			app.startUp();
			// loading screen
			app.loadingScreen();
			// get the gamedata from the main menu
			GameData data = app.mainMenu();
			// show the loading screen
			app.loadingScreen();
			// and start the game!
			app.start(data.getMap(),data.getWind(),data.getPic(),data.getTwoPlayer());
		} catch (InterruptedException e) {   // if there was any exceptions the show them, close the program
			e.printStackTrace();
			System.exit(0);
			return;
		}
	}
}
